<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Geometric Transformations of Images</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d5/d10/tutorial_js_root.html">OpenCV.js Tutorials</a></li><li class="navelem"><a class="el" href="../../d2/df0/tutorial_js_table_of_contents_imgproc.html">Image Processing</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Geometric Transformations of Images </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><h2>Goals </h2>
<ul>
<li>Learn how to apply different geometric transformation to images like translation, rotation, affine transformation etc.</li>
<li>You will learn these functions: <b><a class="el" href="../../da/d54/group__imgproc__transform.html#ga47a974309e9102f5f08231edc7e7529d" title="Resizes an image. ">cv.resize</a></b>, <b><a class="el" href="../../da/d54/group__imgproc__transform.html#ga0203d9ee5fcd28d40dbc4a1ea4451983" title="Applies an affine transformation to an image. ">cv.warpAffine</a></b>, <b><a class="el" href="../../da/d54/group__imgproc__transform.html#ga8f6d378f9f8eebb5cb55cd3ae295a999" title="Calculates an affine transform from three pairs of the corresponding points. ">cv.getAffineTransform</a></b> and <b><a class="el" href="../../da/d54/group__imgproc__transform.html#gaf73673a7e8e18ec6963e3774e6a94b87" title="Applies a perspective transformation to an image. ">cv.warpPerspective</a></b></li>
</ul>
<h2>Transformations </h2>
<h3>Scaling</h3>
<p>Scaling is just resizing of the image. OpenCV comes with a function <b><a class="el" href="../../da/d54/group__imgproc__transform.html#ga47a974309e9102f5f08231edc7e7529d" title="Resizes an image. ">cv.resize()</a></b> for this purpose. The size of the image can be specified manually, or you can specify the scaling factor. Different interpolation methods are used. Preferable interpolation methods are <b><a class="el" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121acf959dca2480cc694ca016b81b442ceb">cv.INTER_AREA</a></b> for shrinking and <b><a class="el" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121a55e404e7fa9684af79fe9827f36a5dc1">cv.INTER_CUBIC</a></b> (slow) &amp; <b><a class="el" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121ac97d8e4880d8b5d509e96825c7522deb">cv.INTER_LINEAR</a></b> for zooming.</p>
<p>We use the function: <b><a class="el" href="../../da/d54/group__imgproc__transform.html#ga47a974309e9102f5f08231edc7e7529d" title="Resizes an image. ">cv.resize</a> (src, dst, dsize, fx = 0, fy = 0, interpolation = <a class="el" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121ac97d8e4880d8b5d509e96825c7522deb">cv.INTER_LINEAR</a>)</b> </p><dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">src</td><td>input image </td></tr>
    <tr><td class="paramname">dst</td><td>output image; it has the size dsize (when it is non-zero) or the size computed from <a class="el" href="../../df/d5b/namespacecv_1_1gapi_1_1streaming.html#a0a915e69f4cc8284293e40fc9ffbf157" title="Gets dimensions from Mat. ">src.size()</a>, fx, and fy; the type of dst is the same as of src. </td></tr>
    <tr><td class="paramname">dsize</td><td>output image size; if it equals zero, it is computed as: <p class="formulaDsp">
\[𝚍𝚜𝚒𝚣𝚎 = 𝚂𝚒𝚣𝚎(𝚛𝚘𝚞𝚗𝚍(𝚏𝚡*𝚜𝚛𝚌.𝚌𝚘𝚕𝚜), 𝚛𝚘𝚞𝚗𝚍(𝚏𝚢*𝚜𝚛𝚌.𝚛𝚘𝚠𝚜))\]
</p>
 Either dsize or both fx and fy must be non-zero. </td></tr>
    <tr><td class="paramname">fx</td><td>scale factor along the horizontal axis; when it equals 0, it is computed as <p class="formulaDsp">
\[(𝚍𝚘𝚞𝚋𝚕𝚎)𝚍𝚜𝚒𝚣𝚎.𝚠𝚒𝚍𝚝𝚑/𝚜𝚛𝚌.𝚌𝚘𝚕𝚜\]
</p>
</td></tr>
    <tr><td class="paramname">fy</td><td>scale factor along the vertical axis; when it equals 0, it is computed as <p class="formulaDsp">
\[(𝚍𝚘𝚞𝚋𝚕𝚎)𝚍𝚜𝚒𝚣𝚎.𝚑𝚎𝚒𝚐𝚑𝚝/𝚜𝚛𝚌.𝚛𝚘𝚠𝚜\]
</p>
 </td></tr>
    <tr><td class="paramname">interpolation</td><td>interpolation method(see <b><a class="el" href="../../da/d54/group__imgproc__transform.html#ga5bb5a1fea74ea38e1a5445ca803ff121" title="interpolation algorithm ">cv.InterpolationFlags</a></b>)</td></tr>
  </table>
  </dd>
</dl>
<h2>Try it </h2>
<p> 
<iframe src="../../js_geometric_transformations_resize.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h3>Translation</h3>
<p>Translation is the shifting of object's location. If you know the shift in (x,y) direction, let it be \((t_x,t_y)\), you can create the transformation matrix \(\textbf{M}\) as follows:</p>
<p class="formulaDsp">
\[M = \begin{bmatrix} 1 &amp; 0 &amp; t_x \\ 0 &amp; 1 &amp; t_y \end{bmatrix}\]
</p>
<p>We use the function: <b><a class="el" href="../../da/d54/group__imgproc__transform.html#ga0203d9ee5fcd28d40dbc4a1ea4451983" title="Applies an affine transformation to an image. ">cv.warpAffine</a> (src, dst, M, dsize, flags = <a class="el" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121ac97d8e4880d8b5d509e96825c7522deb">cv.INTER_LINEAR</a>, borderMode = <a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838" title="iiiiii|abcdefgh|iiiiiii with some specified i ">cv.BORDER_CONSTANT</a>, borderValue = new <a class="el" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">cv.Scalar()</a>)</b> </p><dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">src</td><td>input image. </td></tr>
    <tr><td class="paramname">dst</td><td>output image that has the size dsize and the same type as src. </td></tr>
    <tr><td class="paramname">Mat</td><td>2 × 3 transformation matrix(cv.CV_64FC1 type). </td></tr>
    <tr><td class="paramname">dsize</td><td>size of the output image. </td></tr>
    <tr><td class="paramname">flags</td><td>combination of interpolation methods(see <a class="el" href="../../da/d54/group__imgproc__transform.html#ga5bb5a1fea74ea38e1a5445ca803ff121" title="interpolation algorithm ">cv.InterpolationFlags</a>) and the optional flag WARP_INVERSE_MAP that means that M is the inverse transformation ( 𝚍𝚜𝚝→𝚜𝚛𝚌 ) </td></tr>
    <tr><td class="paramname">borderMode</td><td>pixel extrapolation method (see <a class="el" href="../../d2/de8/group__core__array.html#ga209f2f4869e304c82d07739337eae7c5">cv.BorderTypes</a>); when borderMode = BORDER_TRANSPARENT, it means that the pixels in the destination image corresponding to the "outliers" in the source image are not modified by the function. </td></tr>
    <tr><td class="paramname">borderValue</td><td>value used in case of a constant border; by default, it is 0.</td></tr>
  </table>
  </dd>
</dl>
<p>rows.</p>
<h2>Try it </h2>
<p> 
<iframe src="../../js_geometric_transformations_warpAffine.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h3>Rotation</h3>
<p>Rotation of an image for an angle \(\theta\) is achieved by the transformation matrix of the form</p>
<p class="formulaDsp">
\[M = \begin{bmatrix} cos\theta &amp; -sin\theta \\ sin\theta &amp; cos\theta \end{bmatrix}\]
</p>
<p>But OpenCV provides scaled rotation with adjustable center of rotation so that you can rotate at any location you prefer. Modified transformation matrix is given by</p>
<p class="formulaDsp">
\[\begin{bmatrix} \alpha &amp; \beta &amp; (1- \alpha ) \cdot center.x - \beta \cdot center.y \\ - \beta &amp; \alpha &amp; \beta \cdot center.x + (1- \alpha ) \cdot center.y \end{bmatrix}\]
</p>
<p>where:</p>
<p class="formulaDsp">
\[\begin{array}{l} \alpha = scale \cdot \cos \theta , \\ \beta = scale \cdot \sin \theta \end{array}\]
</p>
<p>We use the function: <b><a class="el" href="../../da/d54/group__imgproc__transform.html#gafbbc470ce83812914a70abfb604f4326" title="Calculates an affine matrix of 2D rotation. ">cv.getRotationMatrix2D</a> (center, angle, scale)</b> </p><dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">center</td><td>center of the rotation in the source image. </td></tr>
    <tr><td class="paramname">angle</td><td>rotation angle in degrees. Positive values mean counter-clockwise rotation (the coordinate origin is assumed to be the top-left corner). </td></tr>
    <tr><td class="paramname">scale</td><td>isotropic scale factor.</td></tr>
  </table>
  </dd>
</dl>
<h2>Try it </h2>
<p> 
<iframe src="../../js_geometric_transformations_rotateWarpAffine.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h3>Affine Transformation</h3>
<p>In affine transformation, all parallel lines in the original image will still be parallel in the output image. To find the transformation matrix, we need three points from input image and their corresponding locations in output image. Then <b><a class="el" href="../../da/d54/group__imgproc__transform.html#ga8f6d378f9f8eebb5cb55cd3ae295a999" title="Calculates an affine transform from three pairs of the corresponding points. ">cv.getAffineTransform</a></b> will create a 2x3 matrix which is to be passed to <b><a class="el" href="../../da/d54/group__imgproc__transform.html#ga0203d9ee5fcd28d40dbc4a1ea4451983" title="Applies an affine transformation to an image. ">cv.warpAffine</a></b>.</p>
<p>We use the function: <b><a class="el" href="../../da/d54/group__imgproc__transform.html#ga8f6d378f9f8eebb5cb55cd3ae295a999" title="Calculates an affine transform from three pairs of the corresponding points. ">cv.getAffineTransform</a> (src, dst)</b></p>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">src</td><td>three points([3, 1] size and cv.CV_32FC2 type) from input imag. </td></tr>
    <tr><td class="paramname">dst</td><td>three corresponding points([3, 1] size and cv.CV_32FC2 type) in output image.</td></tr>
  </table>
  </dd>
</dl>
<h2>Try it </h2>
<p> 
<iframe src="../../js_geometric_transformations_getAffineTransform.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
</p>
<h3>Perspective Transformation</h3>
<p>For perspective transformation, you need a 3x3 transformation matrix. Straight lines will remain straight even after the transformation. To find this transformation matrix, you need 4 points on the input image and corresponding points on the output image. Among these 4 points, 3 of them should not be collinear. Then transformation matrix can be found by the function <b><a class="el" href="../../da/d54/group__imgproc__transform.html#ga20f62aa3235d869c9956436c870893ae" title="Calculates a perspective transform from four pairs of the corresponding points. ">cv.getPerspectiveTransform</a></b>. Then apply <b><a class="el" href="../../da/d54/group__imgproc__transform.html#gaf73673a7e8e18ec6963e3774e6a94b87" title="Applies a perspective transformation to an image. ">cv.warpPerspective</a></b> with this 3x3 transformation matrix.</p>
<p>We use the functions: <b><a class="el" href="../../da/d54/group__imgproc__transform.html#gaf73673a7e8e18ec6963e3774e6a94b87" title="Applies a perspective transformation to an image. ">cv.warpPerspective</a> (src, dst, M, dsize, flags = <a class="el" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121ac97d8e4880d8b5d509e96825c7522deb">cv.INTER_LINEAR</a>, borderMode = <a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838" title="iiiiii|abcdefgh|iiiiiii with some specified i ">cv.BORDER_CONSTANT</a>, borderValue = new <a class="el" href="../../dc/d84/group__core__basic.html#ga599fe92e910c027be274233eccad7beb">cv.Scalar()</a>)</b></p>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">src</td><td>input image. </td></tr>
    <tr><td class="paramname">dst</td><td>output image that has the size dsize and the same type as src. </td></tr>
    <tr><td class="paramname">Mat</td><td>3 × 3 transformation matrix(cv.CV_64FC1 type). </td></tr>
    <tr><td class="paramname">dsize</td><td>size of the output image. </td></tr>
    <tr><td class="paramname">flags</td><td>combination of interpolation methods (<a class="el" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121ac97d8e4880d8b5d509e96825c7522deb">cv.INTER_LINEAR</a> or <a class="el" href="../../da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121aa5521d8e080972c762467c45f3b70e6c">cv.INTER_NEAREST</a>) and the optional flag WARP_INVERSE_MAP, that sets M as the inverse transformation (𝚍𝚜𝚝→𝚜𝚛𝚌). </td></tr>
    <tr><td class="paramname">borderMode</td><td>pixel extrapolation method (<a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aed2e4346047e265c8c5a6d0276dcd838" title="iiiiii|abcdefgh|iiiiiii with some specified i ">cv.BORDER_CONSTANT</a> or <a class="el" href="../../d2/de8/group__core__array.html#gga209f2f4869e304c82d07739337eae7c5aa1de4cff95e3377d6d0cbe7569bd4e9f" title="aaaaaa|abcdefgh|hhhhhhh ">cv.BORDER_REPLICATE</a>). </td></tr>
    <tr><td class="paramname">borderValue</td><td>value used in case of a constant border; by default, it is 0.</td></tr>
  </table>
  </dd>
</dl>
<p><b><a class="el" href="../../da/d54/group__imgproc__transform.html#ga20f62aa3235d869c9956436c870893ae" title="Calculates a perspective transform from four pairs of the corresponding points. ">cv.getPerspectiveTransform</a> (src, dst)</b></p>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">src</td><td>coordinates of quadrangle vertices in the source image. </td></tr>
    <tr><td class="paramname">dst</td><td>coordinates of the corresponding quadrangle vertices in the destination image.</td></tr>
  </table>
  </dd>
</dl>
<h2>Try it </h2>
<p> 
<iframe src="../../js_geometric_transformations_warpPerspective.html" width="100%"
        onload="this.style.height=this.contentDocument.body.scrollHeight +'px';">
</iframe>
 </p>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:37 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
